package cn.hg.jbsa.admin.provider;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import com.jfinal.kit.Kv;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.SqlPara;

import cn.hg.jboot.core.BeanStatus;
import cn.hg.jbsa.admin.model.JbsaOrg;
import cn.hg.jbsa.admin.service.JbsaOrgService;
import cn.hutool.core.util.StrUtil;
import io.jboot.aop.annotation.Bean;
import io.jboot.db.model.Columns;
import io.jboot.service.JbootServiceBase;
import io.jboot.utils.CacheUtil;

@Bean
public class JbsaOrgServiceProvider extends JbootServiceBase<JbsaOrg> implements JbsaOrgService {
    /**
     * @param list
     * @param parentId
     *
     * @return
     */
    private List<JbsaOrg> buildTree(final List<JbsaOrg> list, Integer parentId) {
        List<JbsaOrg> tree = new ArrayList<>();

        for (JbsaOrg org : list) {

            if (parentId.equals(org.getParentId())) {
                tree.add(org);
            }

        }

        for (JbsaOrg org : tree) {
            org.setChildren(this.buildTree(list, org.getId()));
        }

        tree.sort(new Comparator<JbsaOrg>() {

            @Override
            public int compare(JbsaOrg o1, JbsaOrg o2) {
                return o1.getSortNum().compareTo(o2.getSortNum());
            }

        });
        return tree;
    }

    /**
     * @param org
     */
    public void del(JbsaOrg org) {
        this.del(org, true);
    }

    /**
     * @param org
     * @param withChildren
     */
    public void del(JbsaOrg org, boolean withChildren) {

        if (withChildren) {
            this.delWithChildren(org);
        } else {
            org.setStatus(BeanStatus.del.name());
            org.update();
        }

    }

    /**
     * @param org
     */
    private void delWithChildren(JbsaOrg org) {
        org.setStatus(BeanStatus.del.name());
        org.update();
        List<JbsaOrg> childrenList = JbsaOrg.dao.find("SELECT * FROM jbsa_org WHERE status <> ? AND parent_id = ?",
            BeanStatus.del.name(), org.getId());

        for (JbsaOrg child : childrenList) {
            child.setStatus(BeanStatus.del.name());
            child.update();
            this.delWithChildren(child);
        }

    }

    @Override
    public List<JbsaOrg> findPageByKv(Integer page, Integer limit, Kv para) {
        SqlPara sqlPara = Db.getSqlPara("system.findOrg", para);

        @SuppressWarnings("unchecked")
        List<JbsaOrg> list = this.getDao().find(sqlPara);

        return list;

    }

    /**
     * @return
     */
    @Override
    public List<JbsaOrg> getTree() {
        List<JbsaOrg> tree = CacheUtil.get("JbsaOrg", "tree");

        List<JbsaOrg> list = JbsaOrg.dao.find("SELECT * FROM jbsa_org WHERE status=?", BeanStatus.on.name());
        tree = this.buildTree(list, JbsaOrg.TOP_ID);

        JbsaOrg org = new JbsaOrg();
        org.setId(JbsaOrg.TOP_ID);
        org.setName("-- 顶层 --");
        org.setParentId(JbsaOrg.TOP_ID);
        org.setStatus(BeanStatus.on.name());
        org.setType("company");
        org.setCreatorId(1);
        org.setEditorId(1);
        org.setLayerNum(0);

        tree.add(JbsaOrg.TOP_ID, org);

        return tree;
    }

    @Override
    public void updateChildredIds(JbsaOrg bean) {
        if (null == bean) {
            return;
        }

        String childrenIds = Db.queryFirst("SELECT GROUP_CONCAT(id) FROM jbsa_org WHERE status<>'del' AND parent_id=?",
            bean.getId());
        bean.setChildrenIds(childrenIds);
        this.update(bean);
    }

    /**
     * @param bean
     */
    public void updateOrgChildredIds(JbsaOrg bean) {

        if (null == bean) {
            return;
        }

        String childrenIds = Db.queryFirst("SELECT GROUP_CONCAT(id) FROM jbsa_org WHERE status <> ? AND parent_id=?",
            BeanStatus.del.name(), bean.getId());

        bean.setChildrenIds(childrenIds);
        bean.update();
    }

    @Override
    public void updateStatus(JbsaOrg bean, String status) {
        this.updateStatusWithChildren(bean, status);
    }

    private void updateStatusWithChildren (JbsaOrg bean, String status) {
        if (!StrUtil.equals(bean.getStatus(), status)) {
            bean.setStatus(status);
            this.update(bean);
        }


        List<JbsaOrg> childrenList =
            this.findListByColumns(Columns.create("parent_id", bean.getId()).ne("status", BeanStatus.del.name()));

        for (JbsaOrg child : childrenList) {
            if (!StrUtil.equals(child.getStatus(), status)) {
                child.setStatus(status);
                this.update(child);
            }
            this.updateStatusWithChildren(child, status);
        }

    }

}
